package com.mlethe.library.recyclerview.decoration;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import com.mlethe.library.recyclerview.listener.ItemDecorationListener;

/**
 * 分割线(StaggeredGridLayoutManager 模式分割线会占据item的高度)
 *
 * @author Mlethe
 * @date 2018/1/11
 */
public class GridItemDecoration extends RecyclerView.ItemDecoration {
    private Context mContext;
    private Drawable mDivider;
    private int size;
    private boolean isShowLeft, isShowTop, isShowRight, isShowBottom, isShowVertical = true, isShowHorizontal = true;
    /**
     * 最后一行未占满的竖直分割线是否显示
     */
    private boolean isShowLast = true;

    private ItemDecorationListener mItemDecorationListener;

    public GridItemDecoration(Context context) {
        this.mContext = context.getApplicationContext();
        size = dp2px(0.5f);
    }

    /**
     * 设置drawable
     *
     * @param drawableId
     */
    public GridItemDecoration setDrawable(@DrawableRes int drawableId) {
        return setDrawable(ContextCompat.getDrawable(mContext, drawableId));
    }

    /**
     * 设置drawable
     *
     * @param drawable
     */
    public GridItemDecoration setDrawable(Drawable drawable) {
        mDivider = drawable;
        return this;
    }

    /**
     * 设置颜色
     *
     * @param colorRes
     */
    public GridItemDecoration setColor(@ColorRes int colorRes) {
        return setColorInt(ContextCompat.getColor(mContext, colorRes));
    }

    /**
     * 设置颜色
     *
     * @param color
     */
    public GridItemDecoration setColorInt(@ColorInt int color) {
        mDivider = new ColorDrawable(color);
        return this;
    }

    /**
     * 设置颜色
     *
     * @param colorString
     */
    public GridItemDecoration setColor(String colorString) {
        return setColorInt(Color.parseColor(colorString));
    }

    /**
     * 设置分割线大小
     *
     * @param size dp
     * @return
     */
    public GridItemDecoration setSize(float size) {
        return setSize(dp2px(size));
    }

    /**
     * 设置分割线大小
     *
     * @param size px
     * @return
     */
    public GridItemDecoration setSize(int size) {
        this.size = size;
        return this;
    }

    /**
     * 四周是否显示分割线
     *
     * @param left   true 显示，false 不显示
     * @param top    true 显示，false 不显示
     * @param right  true 显示，false 不显示
     * @param bottom true 显示，false 不显示
     * @return
     */
    public GridItemDecoration setAroundShow(boolean left, boolean top, boolean right, boolean bottom) {
        this.isShowLeft = left;
        this.isShowTop = top;
        this.isShowRight = right;
        this.isShowBottom = bottom;
        return this;
    }

    /**
     * 是否显示垂直线
     *
     * @param show true 显示，false 不显示
     * @return
     */
    public GridItemDecoration setVerticalShow(boolean show) {
        isShowVertical = show;
        return this;
    }

    /**
     * 是否显示水平线
     *
     * @param show true 显示，false 不显示
     * @return
     */
    public GridItemDecoration setHorizontalShow(boolean show) {
        isShowHorizontal = show;
        return this;
    }

    /**
     * 最后一个item未占满的 竖直\水平 分割线是否显示
     *
     * @param show true 显示，false 不显示
     * @return
     */
    public GridItemDecoration setLastShow(boolean show) {
        isShowLast = show;
        return this;
    }

    /**
     * 设置自定义分割线
     *
     * @param itemDecorationListener
     * @return
     */
    public GridItemDecoration setItemDecorationListener(ItemDecorationListener itemDecorationListener) {
        this.mItemDecorationListener = itemDecorationListener;
        return this;
    }

    /**
     * dp转px
     *
     * @param dp
     * @return
     */
    private int dp2px(float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());
    }

    /**
     * 设置条目周边的偏移量
     *
     * @param outRect
     * @param view
     * @param parent
     * @param state
     */
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (!isShowHorizontal && !isShowVertical) {
            return;
        } else if (size == 0) {
            return;
        }
        int spanCount = getSpanCount(parent);
        if (spanCount == -1) {
            return;
        }
        int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
        if (position < 0) {
            return;
        }
        int itemCount = parent.getAdapter().getItemCount();
        if (position >= itemCount) {
            return;
        }
        if (mItemDecorationListener != null) {
            int startPosition = mItemDecorationListener.getStart();
            int dataSize = mItemDecorationListener.getDrawCount();
            if (startPosition >= 0 && position >= startPosition && dataSize > 0) {
                position -= startPosition;
                itemCount = dataSize;
                if (position >= itemCount) {
                    return;
                }
            } else {
                return;
            }
        }
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
            if (orientation == StaggeredGridLayoutManager.HORIZONTAL) {
                int left = 0;
                int top;
                int right = size;
                int bottom;
                // 等差数列
                int eachHeight = (spanCount - 1) * size / spanCount;
                if (isShowTop && isShowBottom) {
                    eachHeight = (spanCount + 1) * size / spanCount;
                    int dl = Math.abs(size - eachHeight);
                    // 第一行
                    if (isStaggeredFirstRow(position, spanCount)) {
                        top = size;
                    } else {
                        top = (spanCount - position % spanCount) * dl;
                    }
                    bottom = eachHeight - top;
                } else {
                    if (isShowTop) {
                        eachHeight = size;
                    } else if (isShowBottom) {
                        eachHeight = size;
                    }
                    int dl = size - eachHeight;
                    if (isShowTop) {
                        top = size;
                    } else {
                        top = position % spanCount * dl;
                    }
                    if (!isShowLast && position == itemCount - 1 && !isStaggeredLastRow(position, spanCount)) {
                        bottom = 0;
                    } else {
                        bottom = eachHeight - top;
                    }
                }

                if (!isShowHorizontal) {
                    top = 0;
                    bottom = 0;
                }
                if (!isShowVertical) {
                    right = 0;
                } else {
                    // 第一列
                    if (isShowLeft && isStaggeredFirstColumn(position, spanCount)) {
                        left = size;
                    }
                    // 最后一列
                    if (!isShowRight && isStaggeredLastColumn(position, itemCount, spanCount)) {
                        right = 0;
                    }
                }
                outRect.set(left, top, right, bottom);
                return;
            }
        }
        int left;
        int top = 0;
        int right;
        int bottom = size;
        // 等差数列
        int eachWidth = (spanCount - 1) * size / spanCount;
        if (isShowLeft && isShowRight) {
            eachWidth = (spanCount + 1) * size / spanCount;
            int dl = Math.abs(size - eachWidth);
            // 第一列
            if (isFirstColumn(position, spanCount)) {
                left = size;
            } else {
                left = (spanCount - position % spanCount) * dl;
            }
            right = eachWidth - left;
        } else {
            if (isShowLeft) {
                eachWidth = size;
            } else if (isShowRight) {
                eachWidth = size;
            }
            int dl = size - eachWidth;
            if (isShowLeft) {
                left = size;
            } else {
                left = position % spanCount * dl;
            }
            if (!isShowLast && position == itemCount - 1 && !isLastColumn(position, spanCount)) {
                right = 0;
            } else {
                right = eachWidth - left;
            }
        }
        if (!isShowVertical) {
            right = 0;
            left = 0;
        }
        if (!isShowHorizontal) {
            bottom = 0;
        } else {
            // 第一行
            if (isShowTop && isFirstRow(position, spanCount)) {
                top = size;
            }
            // 最后一行
            if (!isShowBottom && isLastRow(position, itemCount, spanCount)) {
                bottom = 0;
            }
        }
        outRect.set(left, top, right, bottom);
    }

    /**
     * 绘制分割线
     *
     * @param canvas
     * @param parent
     * @param state
     */
    @Override
    public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
        mContext = null;
        if (mDivider == null) {
            return;
        } else if (!isShowHorizontal && !isShowVertical) {
            return;
        } else if (size == 0) {
            return;
        }
        // 列数
        int spanCount = getSpanCount(parent);
        if (spanCount == -1) {
            return;
        }
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
            if (orientation == StaggeredGridLayoutManager.HORIZONTAL) {
                drawStaggered(canvas, parent, spanCount);
                return;
            }
        }
        draw(canvas, parent, spanCount);
    }

    /**
     * 绘制在图层的最上层
     *
     * @param canvas
     * @param parent
     * @param state
     */
    @Override
    public void onDrawOver(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
    }

    /**
     * 绘制 StaggeredGridLayoutManager.HORIZONTAL
     *
     * @param canvas
     * @param parent
     * @param spanCount
     */
    private void drawStaggered(Canvas canvas, RecyclerView parent, int spanCount) {
        // 绘制
        int childCount = parent.getChildCount();
        int itemCount = parent.getAdapter().getItemCount();
        int startPosition = -1;
        if (mItemDecorationListener != null) {
            startPosition = mItemDecorationListener.getStart();
            int dataSize = mItemDecorationListener.getDrawCount();
            if (startPosition >= 0 && dataSize > 0) {
                itemCount = dataSize;
            } else {
                return;
            }
        }
        for (int i = 0; i < childCount; i++) {
            View childView = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(childView);

            if (mItemDecorationListener != null && startPosition >= 0) {
                if (position < startPosition) {
                    continue;
                }
                position -= startPosition;
            }

            if (position < 0 || position >= itemCount) {
                continue;
            }
            // 计算水平分割线的位置
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childView.getLayoutParams();
            // 画水平分隔线
            if (isShowHorizontal) {
                // 第一行
                if (isStaggeredFirstRow(position, spanCount)) {
                    if (isShowTop) {
                        int left = childView.getLeft() - layoutParams.leftMargin;
                        if (isShowVertical && isShowLeft && isStaggeredFirstColumn(position, spanCount)) {
                            left -= size;
                        }
                        int right = childView.getRight() + layoutParams.rightMargin;
                        if (isShowVertical) {
                            if (!isShowRight && isStaggeredLastColumn(position, itemCount, spanCount)) {
                            } else {
                                right += size;
                            }
                        }
                        int bottom = childView.getTop() - layoutParams.topMargin;
                        int top = bottom - size;
                        mDivider.setBounds(left, top, right, bottom);
                        mDivider.draw(canvas);
                    }
                }
                // 最后一行
                if (isStaggeredLastRow(position, spanCount)) {
                    if (isShowBottom) {
                        int left = childView.getLeft() - layoutParams.leftMargin;
                        if (isShowVertical && isShowLeft && isStaggeredFirstColumn(position, spanCount)) {
                            left -= size;
                        }
                        int right = childView.getRight() + layoutParams.rightMargin;
                        if (isShowVertical) {
                            if (!isShowRight && isStaggeredLastColumn(position, itemCount, spanCount)) {
                            } else {
                                right += size;
                            }
                        }
                        int top = childView.getBottom() + layoutParams.topMargin;
                        int bottom = top + size;
                        mDivider.setBounds(left, top, right, bottom);
                        mDivider.draw(canvas);
                    }
                } else {
                    if (!isShowLast && position == itemCount - 1 && !isStaggeredLastRow(position, spanCount)) {
                        continue;
                    }
                    int left = childView.getLeft() - layoutParams.leftMargin;
                    if (isShowVertical && isShowLeft && isStaggeredFirstColumn(position, spanCount)) {
                        left -= size;
                    }
                    int right = childView.getRight() + layoutParams.rightMargin;
                    if (isShowVertical) {
                        if (!isShowRight && isStaggeredLastColumn(position, itemCount, spanCount)) {
                        } else {
                            right += size;
                        }
                    }
                    int top = childView.getBottom() + layoutParams.topMargin;
                    int bottom = top + size;
                    mDivider.setBounds(left, top, right, bottom);
                    mDivider.draw(canvas);
                }
            }
            // 画垂直分割线
            if (isShowVertical) {
                // 第一列
                if (isStaggeredFirstColumn(position, spanCount)) {
                    if (isShowLeft) {
                        int top = childView.getTop() - layoutParams.topMargin;
                        int bottom = childView.getBottom() + layoutParams.bottomMargin;
                        int right = childView.getLeft() - layoutParams.leftMargin;
                        int left = right - size;
                        mDivider.setBounds(left, top, right, bottom);
                        mDivider.draw(canvas);
                    }
                }
                // 最后一列
                if (!isShowRight && isStaggeredLastColumn(position, itemCount, spanCount)) {
                    continue;
                }
                int top = childView.getTop() - layoutParams.topMargin;
                int bottom = childView.getBottom() + layoutParams.bottomMargin;
                int left = childView.getRight() - layoutParams.leftMargin;
                int right = left + size;
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }
        }
    }

    /**
     * 绘制
     *
     * @param canvas
     * @param parent
     * @param spanCount
     */
    private void draw(Canvas canvas, RecyclerView parent, int spanCount) {
        // 绘制
        int childCount = parent.getChildCount();
        int itemCount = parent.getAdapter().getItemCount();
        int startPosition = -1;
        if (mItemDecorationListener != null) {
            startPosition = mItemDecorationListener.getStart();
            int dataSize = mItemDecorationListener.getDrawCount();
            if (startPosition >= 0 && dataSize > 0) {
                itemCount = dataSize;
            } else {
                return;
            }
        }
        for (int i = 0; i < childCount; i++) {
            View childView = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(childView);

            if (mItemDecorationListener != null && startPosition >= 0) {
                if (position < startPosition) {
                    continue;
                }
                position -= startPosition;
            }

            if (position < 0 || position >= itemCount) {
                continue;
            }
            // 计算水平分割线的位置
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childView.getLayoutParams();
            // 画水平分隔线
            if (isShowHorizontal) {
                // 第一行
                if (isFirstRow(position, spanCount) && isShowTop) {
                    int left = childView.getLeft() - layoutParams.leftMargin;
                    if (isShowVertical) {
                        if (!isShowLeft && isFirstColumn(position, spanCount)) {
                        } else {
                            left -= size;
                        }
                    }
                    int right = childView.getRight() + layoutParams.leftMargin;
                    if (isShowVertical && isShowRight && isLastColumn(position, spanCount)) {
                        right += size;
                    }
                    int bottom = childView.getTop() - layoutParams.topMargin;
                    int top = bottom - size;
                    mDivider.setBounds(left, top, right, bottom);
                    mDivider.draw(canvas);
                }
                // 最后一行
                if (isLastRow(position, itemCount, spanCount)) {
                    if (isShowBottom) {
                        int left = childView.getLeft() - layoutParams.leftMargin;
                        if (isShowVertical && isShowLeft && isFirstColumn(position, spanCount)) {
                            left -= size;
                        }
                        int right = childView.getRight() + layoutParams.leftMargin;
                        if (isShowVertical) {
                            if (!isShowRight && isLastColumn(position, spanCount)) {
                            } else if (!isShowLast && position == itemCount - 1 && !isLastColumn(position, spanCount)) {
                            } else {
                                right += size;
                            }
                        }
                        int top = childView.getBottom() + layoutParams.bottomMargin;
                        int bottom = top + size;
                        mDivider.setBounds(left, top, right, bottom);
                        mDivider.draw(canvas);
                    }
                } else {
                    int left = childView.getLeft() - layoutParams.leftMargin;
                    if (isShowVertical) {
                        if (!isShowLeft && isFirstColumn(position, spanCount)) {
                        } else {
                            left -= size;
                        }
                    }
                    int right = childView.getRight() + layoutParams.leftMargin;
                    if (isShowVertical && isShowRight && isLastColumn(position, spanCount)) {
                        right += size;
                    }
                    int top = childView.getBottom() + layoutParams.bottomMargin;
                    int bottom = top + size;
                    mDivider.setBounds(left, top, right, bottom);
                    mDivider.draw(canvas);
                }
            }
            // 画垂直分割线
            if (isShowVertical) {
                // 第一列
                if (isFirstColumn(position, spanCount) && isShowLeft) {
                    int top = childView.getTop() + layoutParams.topMargin;
                    int bottom = childView.getBottom() + layoutParams.bottomMargin;
                    int right = childView.getLeft() - layoutParams.leftMargin;
                    int left = right - size;
                    mDivider.setBounds(left, top, right, bottom);
                    mDivider.draw(canvas);
                }
                if (!isShowLast && position == itemCount - 1 && !isLastColumn(position, spanCount)) {
                    continue;
                }
                // 最后一列
                if (!isShowRight && isLastColumn(position, spanCount)) {
                    continue;
                }
                int top = childView.getTop() + layoutParams.topMargin;
                int bottom = childView.getBottom() + layoutParams.bottomMargin;
                int left = childView.getRight() + layoutParams.rightMargin;
                int right = left + size;
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }
        }
    }

    /**
     * 第一列
     *
     * @return
     */
    private boolean isFirstColumn(int position, int spanCount) {
        // 当前位置%列数 == 0
        return position % spanCount == 0;
    }

    /**
     * 最后一列
     *
     * @return
     */
    private boolean isLastColumn(int position, int spanCount) {
        // 当前位置%列数 == 列数 - 1
        return position % spanCount == spanCount - 1;
    }

    /**
     * 第一行
     *
     * @return
     */
    private boolean isFirstRow(int position, int spanCount) {
        // 当前的位置 < 列数
        return position < spanCount;
    }

    /**
     * 最后一行
     *
     * @return
     */
    private boolean isLastRow(int position, int itemCount, double spanCount) {
        // (当前的位置 + 1) / 列数 == 总数 / 列数
        return Math.ceil((position + 1) / spanCount) == Math.ceil(itemCount / spanCount);
    }

    /**
     * 第一行 StaggeredGridLayoutManager.HORIZONTAL
     *
     * @return
     */
    private boolean isStaggeredFirstRow(int position, int spanCount) {
        // 当前位置%列数 == 0
        return position % spanCount == 0;
    }

    /**
     * 最后一行 StaggeredGridLayoutManager.HORIZONTAL
     *
     * @return
     */
    private boolean isStaggeredLastRow(int position, int spanCount) {
        // 当前位置%列数 == 列数 - 1
        return position % spanCount == spanCount - 1;
    }

    /**
     * 第一列 StaggeredGridLayoutManager.HORIZONTAL
     *
     * @return
     */
    private boolean isStaggeredFirstColumn(int position, int spanCount) {
        // 当前的位置 < 列数
        return position < spanCount;
    }

    /**
     * 最后一列 StaggeredGridLayoutManager.HORIZONTAL
     *
     * @return
     */
    private boolean isStaggeredLastColumn(int position, int itemCount, double spanCount) {
        // (当前的位置 + 1) / 列数 == 总数 / 列数
        return Math.ceil((position + 1) / spanCount) == Math.ceil(itemCount / spanCount);
    }

    /**
     * 获取RecyclerView的列数
     *
     * @param parent
     * @return
     */
    private int getSpanCount(RecyclerView parent) {
        // 获取列数  GridLayout
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            return gridLayoutManager.getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager staggeredGridLayoutManager = ((StaggeredGridLayoutManager) layoutManager);
            return staggeredGridLayoutManager.getSpanCount();
        }
        return -1;
    }
}
